/** @file msg_que.cpp
 * @brief Message Que handling
 * @author    - Robert Zhang <armner@gmail.com>
 *            - Wismy Yao <aheynie@gmail.com>
 * @date 2013-05
 * @version 1.0.0
 * @note
 */
#include "msg_queue.h"
#include "frgui.h"
#include "dialog.h"
#include "key_driver.h"
#include "stdlib.h"


/** 
 * @brief set msgque to a deinfed state
 */
void MsgQue::CREATE_LOCK()
{
    gui_create_lock(&lock);
}
/** 
 * @brief set msgque to a deinfed state
 */
void MsgQue::LOCK()
{
    gui_get_lock(lock);
}
/** 
 * @brief set msgque to a activity state
 */
void MsgQue::UNLOCK()
{
    gui_release_lock(lock);
}

/** @brief MsgQue constructor */
MsgQue::MsgQue()
{
    wr =rd = 0;

    CREATE_LOCK();
}
/**< @brief MsgQue operator 'delete' definitions  */ 
void MsgQue::operator delete(void *t)
{
    port_free(t);
}
/**< @brief MsgQue operator 'new' definitions  */ 
void *MsgQue::operator new(unsigned int len)
{
    void *t;
    t= port_malloc(len);
    
    return t;
}

/**
 * @brief send a message to queue
 * @param HWND hWnd
 * @param int message
 * @param WPARAM wParam
 * @param LPARAM lParam
 * @return int 
 */
int sendMessage(HWND hWnd, int message,WPARAM wParam,LPARAM lParam)
{
    if(!hWnd)
        return -1;

    return ((Widget *)hWnd)->defaultHandler(hWnd, message, wParam, lParam);
}


/**
 * @brief get a message form queue
 * @param PMsg pMsg
 * @return NULL for No message
 */
MsgQue *msgQue=0;

int getMessage(PMsg pMsg)
{
    return msgQue->getMessage(pMsg);
}

int MsgQue::getMessage(PMsg pMsg)
{
    PMsg pMess;
    for(;;)
    {
        int t_int;

        LOCK();
        if(msgQue->wr == msgQue->rd)
        {
            UNLOCK();

            continue;
        }

        pMess = msgQue->msgBuffer + msgQue->rd;

        t_int =msgQue->rd;
        t_int ++; t_int &= QUE_DEPTH_MASK;
        msgQue->rd =t_int;

        UNLOCK();

        //copy msg from FIFO
        {
            pMsg->hWnd = pMess->hWnd;
            pMsg->iMsg = pMess->iMsg;
            pMsg->wParam = pMess->wParam;
            pMsg->lParam = pMess->lParam;
        }


        return 1;
    }
}


/**
 * @brief post a message to queue
 * @param HWND hWnd
 * @param int iMsg
 * @param WPARAM wParam
 * @param LPARAM lParam
 * @return ERR_QUEUE_FULL, ERR_OK
 */
int MsgQue::postMessage(HWND hWnd, int iMsg, WPARAM wParam, LPARAM lParam)
{
    int temp;
    PMsg pMess;

    LOCK();
    temp = msgQue->wr;
    temp ++;
    temp &= QUE_DEPTH_MASK;

    if( temp == msgQue->rd)
    {
        UNLOCK();
        return ERR_QUEUE_FULL;
    }

    pMess =msgQue->msgBuffer + msgQue->wr;
    msgQue->wr =temp;
    UNLOCK();
    
    pMess->hWnd =hWnd;
    pMess->iMsg =iMsg;
    pMess->wParam =wParam;
    pMess->lParam =lParam;

    return ERR_OK;
}

